#include"String.h"
namespace bit
{
     ostream& operator<<(ostream& _cout, const bit::string& s)
     {
         for (int i = 0; i < s._size; i++)
         {
             _cout << s._str[i];
         }
         return _cout;
     }

     istream& operator>>(istream& _cin, bit::string& s)
     {
         char ret;
         while (_cin.get(ret))
         {
             if (ret == ' ' || ret == '\n')
             {
                 return _cin;
             }
             else
             {
                 s += ret;
             }
         }
     }
    string::string(const char* str):_size(strlen(str))
    {
        _capacity = _size;
        _str = new char[_size + 1];
        memcpy(_str, str, _size + 1);
    }

    string::string(const string& s) :_size(strlen(s._str))
    {
        _capacity = s._size;
        _str = new char[_size+1];
        memcpy(_str, s._str, _size + 1);
    }

   string& string::operator=(const string& s)
   {
       string ret = new char[strlen(s._str + 1)];
       ret._capacity = ret._size = strlen(s._str) + 1;
       memcpy(ret._str, s._str, ret._size + 1);
       return ret;
   }

   string::~string()
   {
       delete[] _str;
       _size = _capacity = 0;
       _str = nullptr;
   }
   string::iterator string::begin()
   {
       return _str;
   }
   string::iterator string::end()
   {
       return _str + _size;
   }
   void string::push_back(char c)
   {
       if (_capacity == _size)
       {
           reserve(_capacity > 0 ? 4 : _capacity * 2);
       }
       _str[_size++] = c;
       _str[_size] = '\0';
   }

   string& string::operator+=(char c)
   {
       if (_capacity == _size || _capacity == 0)
       {
           reserve(_capacity == 0 ? 4 : 2 * _capacity);
       }
       _str[_size++] = c;
       _str[_size] = '\0';
       return *this;
   }

   void string::append(const char* str)
   {
       size_t len = strlen(str);
       if (_size + len > _capacity)
       {
           size_t newcapacity = _size + len > 2 * _capacity ? _size + len : 2 * _capacity;
           reserve(newcapacity);
       }
       memcpy(_str + _size, str, _size + 1);
       _size += len;
   }

   string& string::operator+=(const char* str)
   {
       size_t len = strlen(str);
       if (_size + len > _capacity)
       {
           size_t newcapacity = _size + len > 2 * _capacity ? _size + len : 2 * _capacity;
           reserve(newcapacity);
           _capacity = newcapacity;
       }
       memcpy(_str + _size, str, _size + 1);
       _size += len;
       return *this;
   }

   void string::clear()
   {
       _size = 0;
       _str[_size] = '\0';
   }


   void string::swap(string& s)
   {
       std::swap(_str, s._str);
       std::swap(_size, s._size);
       std::swap(_capacity, s._capacity);
   }
   size_t string::size()const
   {
       return _size;
   }

   size_t string::capacity()const
   {
       return _capacity;
   }

   bool string::empty()const
   {
       return _size == 0;
   }

   void string::resize(size_t n, char c )
   {
       if (n < _size)
       {
           _size = n;
           _str[_size] = '\0'; 
       }
       else
       {
           size_t newcapacity = n + _size >= _capacity ? n + _size : 2 * _capacity;
           reserve(newcapacity);
           for (int i = _size; i < _size + n; i++)
           {
               _str[i] = c;
           }
           _capacity = newcapacity;
           _size += n;
           _str[_size] = '\0';
       }
   }

   char& string::operator[](size_t index)
   {
       assert(index < _size);
       return _str[index];
   }

   const char& string::operator[](size_t index)const
   {
       assert(index < _size);
       return _str[index];
   }

   bool string::operator<(const string& s)const
   {
       size_t len1 = 0, len2 = 0;
       while (len1 < _size && len2 < s._size)
       {
           if (_str[len1] < s._str[len2])
           {
               return true;
           }
           else if (_str[len1] > s._str[len2])
           {
               return false;
           }
           else
           {
               len1++;
               len2++;
           }
       }
       return len1 == _size && len2 < s._size;
   }
   
   bool string::operator<=(const string& s)
   {
       return *this < s || *this == s;
   }

   bool string::operator>(const string& s)
   {
       return !(*this < s) && *this != s;
   }

   bool string::operator>=(const string& s)
   {
       return !(*this < s);
   }

   bool string::operator==(const string& s)
   {
       if (_size != s._size)
       {
           return false;
       }
       else
       {
           int i = 0;
           while (i < s._size)
           {
               if (_str[i] != s._str[i])
               {
                   return false;
               }
               i++;
           }
       }
       return true;
   }

   bool string::operator!=(const string& s)
   {
       return !(*this == s);
   }

   const char* string::c_str()const
   {
       return _str;
   }

   void string::reserve(size_t n)
   {
       if (n > _capacity)
       {
           char* tmp = new char[n + 1];
           memcpy(tmp, _str, _size + 1);
           delete[] _str;
           _str = tmp;
           _capacity = n;
       }
   }

   size_t string::find(char c, size_t pos) const
   {
       for (size_t i = 0; i < _size; i++)
       {
           if (_str[i] == c)
           {
               return i;
           }
       }
       return _Meta_npos;
   }

   size_t string::find(const char* s, size_t pos) const
   {
       if (!s || *s == '\0' || pos >= _size)
           return _Meta_npos;
       char*  ret =strstr(_str + pos, s);
       if (ret == nullptr)
       {
           return _Meta_npos;
       }
       return ret - _str;
   }

   string& string::insert(size_t pos, char c)
   {
       assert(pos >= 0 && pos <= _size);
       if (_size == _capacity)
       {
           reserve(_capacity == 0 ? 4 : 2 * _capacity);
       }
       size_t end = _size + 1;
       while (end > pos)
       {
           _str[end] = _str[end - 1];
           end--;
       }
       _str[pos] = c;
       _size += 1;
       return *this;
   }

   string& string::insert(size_t pos, const char* str)
   {
       assert(pos >= 0 && pos <= _size);
       size_t len = strlen(str);
       size_t newcapacity = _size + len >= _capacity ? _size + len : 2 * _capacity;
       reserve(newcapacity);
       size_t end = _size + len - 1;
       while (end > pos+len-1)
       {
           _str[end] = _str[end - len];
           end--;
       }
       for (size_t i = 0; i < len; i++)
       {
           _str[pos + i] = str[i];
       }
       _size += len;
       return *this;
   }

   string& string::erase(size_t pos, size_t len)
   {
       assert(pos < _size);

       if (len ==_Meta_npos || len >= _size - pos)
       {
           _str[pos] = '\0';
           _size = pos;
       }
       else
       {
           memmove(_str + pos, _str + pos + len, _size + 1 - (pos + len));
           _size -= len;
       }
       return *this;
   }
}